// 参考 https://xieguanglei.github.io/blog/post/using-shader-to-optimize-page.html
import { 
  Color, 
  Mesh, 
  MeshBasicMaterial, 
  OrthographicCamera, 
  PlaneBufferGeometry, 
  Scene, 
  ShaderMaterial, 
  Vector3, 
  WebGLRenderer 
} from "three";

const canvas = document.createElement('canvas');
document.body.appendChild(canvas);
canvas.style.width = '100vw';
canvas.style.height = '100vh';

const scene = new Scene();
const renderer = new WebGLRenderer({
  antialias: true,
  alpha: true, // 开启背景透明
  canvas
});
// 设置背景色为透明
renderer.setClearColor(0xff0000, 0);
renderer.autoClearColor = false;

const camera = new OrthographicCamera(
  -1, // left
  1, // right
  1, // top
  -1, // bottom
  -1, // near
  1,  // far
)
const plane = new PlaneBufferGeometry(2, 3)

// 片元着色器
const fragmentShader = `
#ifdef GL_ES
precision mediump float;
#endif

#define PI 3.14159265359

uniform vec2 iResolution;
uniform vec3 iColor;
uniform vec3 iBorderColor;

vec3 circle(vec3 veinsColor){
  // 获取半径大小
  float r = min(iResolution.x, iResolution.y) * 0.504;    
  // 获取中心位置
  vec2 center = vec2(iResolution.x / 2.0, iResolution.y / 2.0);

  vec2 dxy = gl_FragCoord.xy - center;
  float dist = sqrt(dxy.x * dxy.x + dxy.y * dxy.y);

  float p = dist / r;
  p = smoothstep(0.5, 0.505, p);

  return mix(veinsColor, iBorderColor, p);
}

// 使用透明色剪切功能
vec4 clip(vec3 color) {
  float r = min(iResolution.x, iResolution.y) * 0.4;
  vec2 center = vec2(iResolution.x / 2.0, iResolution.y / 2.0);

  vec2 dxy = gl_FragCoord.xy - center;
  float dist = sqrt(dxy.x * dxy.x + dxy.y * dxy.y);

  float opacity = smoothstep(0.8, 0.805, dist/r);

  return vec4(color, 1. - opacity);
}

void main() {
  vec3 color = circle(iColor);

  gl_FragColor = clip(color);
}
`

// const material = new MeshBasicMaterial({ color: 'red' })
const uniforms = {
  iTime: { value: 0},
  iResolution: { value: new Vector3() },
  // 随机产生颜色
  iColor: { value: new Color(0xffffff * Math.random()) },
  iBorderColor: { value: new Color(0xffffff * Math.random()) },
}
const material = new ShaderMaterial({
  fragmentShader,
  uniforms,
  // 支持透明度
  transparent: true,
})
scene.add(new Mesh(plane, material))


function resizeRendererToDisplaySize(renderer: WebGLRenderer) {
  const canvas = renderer.domElement
  const width = canvas.clientWidth
  const height = canvas.clientHeight
  const needResize = canvas.width !== width || canvas.height !== height

  if (needResize) {
    renderer.setSize(width, height, false)
  }

  return needResize
}

function render(time: number): void {
  time *= 0.001

  resizeRendererToDisplaySize(renderer)

  const canvas = renderer.domElement
  uniforms.iResolution.value.set(canvas.width, canvas.height, 1)
  uniforms.iTime.value = time

  renderer.render(scene, camera)

  requestAnimationFrame(render)
}

requestAnimationFrame(render)